// Parse-tree node types.
enum {
  PT_SEQ_EXPR,                   // 0
  PT_EXPR,                       // 1
  PT_IF_EXPR,                    // 2
  PT_TUPLE_EXPR,                 // 3
  PT_TUPLE_COMPONENT,            // 4
  PT_FACTOR,                     // 5
  PT_NUMBER,                     // 6
  PT_SYMBOL,                     // 7
  PT_VAR_NAME,                   // 8
  PT_DATA_CONSTRUCTOR,           // 9
  PT_APPLICATION,                // 10
  PT_CLOSURE,                    // 11
  PT_PATTERN_ALTERNATIVE,        // 12
  PT_PATTERN,                    // 13
  PT_TUPLE_PATTERN_COMPONENT,    // 14
  PT_TEST,                       // 15
  PT_VAR_REF,                    // 16
  PT_PATTERN_VAR,                // 17
  PT_ANONYMOUS_VAR,              // 18
  PT_PATTERN_DATA_CONSTRUCTOR,   // 19
  PT_NULL                        // 20
};

typedef struct _PTREE_NODE PTREE_NODE;
typedef struct _PTREE_NODE_OP_LST PTREE_NODE_OP_LST;

// Used to store a sequence of (operator,operand) pairs which
// crop up frequently in rules like:
//    seqExpr = expr (';' expr)*
//                   \--------/
//                       ^
//                       |
//                       |
//    these get stored in a PTREE_NODE_OP_LST.
//
// The first item ('expr' in this case) will get its own
// field in PTREE_NODE since it's mandatory.
typedef struct _PTREE_NODE_OP_LST {
  // Operator.
  int tk_op;
  // Operand.
  PTREE_NODE *opnd;
  PTREE_NODE_OP_LST *next;
} PTREE_NODE_OP_LST;

typedef struct _PTREE_NODE {
  int type;
  union {
    // PT_SEQ_EXPR
    struct {
      PTREE_NODE *expr0;
      PTREE_NODE_OP_LST *rest_seq;
    };
    // PT_EXPR
    PTREE_NODE *expr;
    // PT_IF_EXPR
    struct {
      PTREE_NODE *test;
      PTREE_NODE *then_part;
      PTREE_NODE *else_part;
    };
    // PT_TUPLE_EXPR
    struct {
      PTREE_NODE *comp0;
      PTREE_NODE_OP_LST *rest_comp;
    };
    // PT_TUPLE_COMPONENT
    struct {
      PTREE_NODE *factor0;
      PTREE_NODE_OP_LST *rest_factor;
    };
    // PT_FACTOR
    PTREE_NODE *factor;
    // PT_NUMBER
    double num;
    // PT_SYMBOL
    char *sym;
    // PT_VAR_NAME
    char *var_name;
    // PT_DATA_CONSTRUCTOR or PT_PATTERN_DATA_CONSTRUCTOR
    struct {
      char *tag;
      union {
        // PT_DATA_CONSTRUCTOR
        PTREE_NODE *tup_expr;
        // PT_PATTERN_DATA_CONSTRUCTOR
        PTREE_NODE *ds_pat;
      };
    };
    // PT_APPLICATION
    struct {
      PTREE_NODE *fn;
      PTREE_NODE *tup_args;
    };
    // PT_CLOSURE
    struct {
      PTREE_NODE *pat_alt0;
      PTREE_NODE_OP_LST *rest_pat_alts;
    };
    // PT_PATTERN_ALTERNATIVE
    struct {
      PTREE_NODE *pat;
      PTREE_NODE *result_seq_expr;
    };
    // PT_PATTERN
    struct {
      PTREE_NODE *tup_pat_cmp0;
      PTREE_NODE_OP_LST *rest_tup_pat_cmp;
    };
    // PT_TUPLE_PATTERN_COMPONENT
    PTREE_NODE *tup_pat_cmp;
    // PT_TEST
    struct {
      char *test_name;
      PTREE_NODE *test_pat;
    };
    // PT_VAR_REF
    char *ref_var;
    // PT_PATTERN_VAR
    char *pat_var;
    // PT_ANONYMOUS_VAR - nothing needed.
    // PT_NULL - nothing needed.
  };
} PTREE_NODE;

typedef struct {
  char *msg;
  int line, col;
} ERR_INFO;

void ptree_free(PTREE_NODE *ptree);
PTREE_NODE *parse(GEN_READ *r, ERR_INFO *err);
void ptree_to_gviz(PTREE_NODE *ptree, char *fname);
